package br.usp.ime.dojo.core.entities;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Timer;
import java.util.TimerTask;

import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PrimaryKey;


import br.usp.ime.dojo.core.exceptions.StartSessionException;
import br.usp.ime.dojo.core.exceptions.UserAlreadyInTheRoomException;
import br.usp.ime.dojo.core.exceptions.UserNotInTheRoomException;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class DojoRoom {
	private final long delayForPilotQueue = 1000*60*7; //7 minutes
	@PrimaryKey
    @Persistent
	private String name;
	@Persistent
	private String description;
	@Persistent
	private String language;
	@Persistent
	private boolean started;
	@Persistent
	private List<User> users;
	@Persistent
	private User pilot, copilot, creator;
	@Persistent
	private Queue<User> pilotUserQueue;
	@Persistent
	private List<String> initialLanguages;
	@Persistent
	private ArrayList<String> selectedLanguages;
	
	
	// TODO: deprecated constructor
	public DojoRoom(String name) {
		this.language = "none";
		this.name = name;
		this.users = new ArrayList<User>();
		this.pilotUserQueue = new LinkedList<User>();
	}

	// TODO: deprecated constructor
	public DojoRoom(String name, String description) {
		this(name);
		this.setDescription(description);
	}
	
	public DojoRoom(String name, String description, User creator){
		this(name,description);
		this.setCreator(creator);
	}
	
	public DojoRoom(String name, String description, User creator, List<String> initialLanguages) {
		this(name, description, creator);
		selectedLanguages = new ArrayList<String>();
		this.initialLanguages = initialLanguages;
		for (String language : initialLanguages) {
			selectedLanguages.add(language);
		}
	}
	
	public String getLanguage() {
		return language;
	}
	
	public void setLanguage(String newLanguage) {
		language = newLanguage;
	}

	public String getName() {
		return name;
	}

	public String getDescription() {
		return description;
	}
	
	public void setDescription(String newDescription) {
		description = newDescription;
	}

	public boolean sessionHasStarted() {
		return started;
	}
	public void swapPilots(){
		pilot = copilot;
		copilot = pollUserFromQueue();
	}
	public void sessionStart() throws StartSessionException {
		if(pilotQueueCount() < 2) throw new StartSessionException("Insufficient users in the pilot queue!");
		
		if(selectedLanguages.size()!=1) throw new StartSessionException("Exactly one language must be selected!");
		
		//TODO
		pilot = pollUserFromQueue();
		copilot = pollUserFromQueue();
		
		initTimerForSwaps();
		
		started = true;		
	}

	private void initTimerForSwaps() {
		Timer timer = new Timer();
		 timer.scheduleAtFixedRate(new TimerTask() {
	            public void run() {
	            	swapPilots();
	            }
	        }, delayForPilotQueue, delayForPilotQueue);
	}

	public void addUser(User user) throws UserAlreadyInTheRoomException {		
		if(isUserHere(user)){
			//throw new UserAlreadyInTheRoomException();
		}
		else{
			users.add(user);
		}
	}
	
	public void removeUser(User user) throws UserNotInTheRoomException{
		if(!isUserHere(user)) throw new UserNotInTheRoomException();
		
		if(getPilot() != null)
			if(getPilot().getName().equals(user.getName()))
				pilot = null;
		
		if(getCopilot() != null)
			if(getCopilot().getName().equals(user.getName()))
				copilot = null;
				
		removeFromPilotQueue(user);
		
		users.remove(user);
	}

	public List<User> getUsers() {
		return users;
	}

	public boolean isUserHere(User user) {
		return users.contains(user);
	}

	public void addToPilotQueue(User user){
		pilotUserQueue.add(user);		
	}

	public boolean pilotQueueIsEmpty() {
		return pilotUserQueue.isEmpty();
	}

	public int pilotQueueCount() {
		return pilotUserQueue.size();
	}

	public User getPilot() {
		return this.pilot;
	}

	public User getCopilot() {
		return this.copilot;
	}
	
	public void setPilot(User user){
		this.pilot = user; 
	}
	
	public void setCopilot(User user){
		this.copilot = user; 
	}

	public User peekUserFromQueue() {
		return pilotUserQueue.peek();
	}

	private User pollUserFromQueue() {
		return pilotUserQueue.poll();
	}

	public void setCreator(User creator) {
		this.creator = creator;
	}

	public User getCreator() {
		return creator;
	}

	public boolean pilotQueueHasUser(User user) {
		return pilotUserQueue.contains(user);
	}

	public void removeFromPilotQueue(User user) {
		
		User u = null;
		for(User usr : users) 
			if(usr.getName().equals(user.getName()))
				u = usr;
		
		if(u != null)
			pilotUserQueue.remove(u);
	}

	public Queue<User> getPilots() {
		return pilotUserQueue;
	}

	public List<String> getSelectedLanguages() {
		return selectedLanguages;
	}
	
	public List<String> getInitialLanguages() {
		return initialLanguages;
	}

	public void toggleLanguageSelection(String language) {
		if (selectedLanguages.contains(language)) {
			selectedLanguages.remove(language);
		} else {
			selectedLanguages.add(language);
		}
		// TODO Auto-generated method stub
		
	}
}
